#include <cstdlib>
#include <cassert>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <string>
#include <getopt.h>
#include "common.h"

// V$(Core).h verilator generate .h and .cpp
#include "VMySoCSim.h"

#ifdef VCD
#include <verilated_vcd_c.h>	// Trace file format header
#endif
using namespace std;

class Emulator
{
private:
    const char* image;    // .bin abspath
    VMySoCSim* top;    //
#ifdef VCD
    VerilatedVcdC* tfp;
#endif

    // control variable
    uint32_t seed;
    uint64_t max_cycles, cycles;
    uint64_t main_times;
    uint64_t log_begin, log_end, log_level;

    static const struct option long_options[];
    static void print_help(const char *file);
    
public:
    Emulator(int argc, const char *argv[]);
    ~Emulator();
    vector<const char *> parse_args(int argc, const char *argv[]);
    void execute();
    void execute_cycles(uint64_t n);
    void single_cycle();
    void read_emu_regs(rtlreg_t *r);
    uint64_t get_cycles() const { return cycles; }
    uint64_t get_max_cycles() const { return max_cycles; }
    // reset for n cycles to support pipelined reset
    void reset_n(uint64_t n){
        while(n--) {
          top->reset = 1;
          top->clock = 0;
          top->eval();
#ifdef VCD
          tfp->dump(main_times++);
#endif
          top->clock = 1;
          top->eval();
          top->reset = 0;
#ifdef VCD
          tfp->dump(main_times++);
#endif
    }
    }
};

